using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using HslCommunication;
using Catastrophe.AutoSulution.TimeCal;

namespace Catastrophe.AutoSulution.TaskM
{
	public class TaskManager<T> : BaseTask where T : class, new()
	{
		/// <summary>
		/// 加载Ini方法之前调用
		/// </summary>
		public Action<T> LoadIniHandler;

		/// <summary>
		/// T实例
		/// </summary>
		public T Tinstance { get; set; }

		/// <summary>
		/// 手动创建对象
		/// </summary>
		public void ManualCreateInstance()
		{
			Type typeFromHandle = typeof(T);
			if (this.Tinstance == null)
			{
				this.Tinstance = (T)Activator.CreateInstance(typeFromHandle);
			}
		}

		/// <summary>
		/// 启动一次
		/// </summary>
		public void Start()
		{
			Type typeFromHandle = typeof(T);
			if (this.Tinstance == null)
			{
				this.Tinstance = (T)Activator.CreateInstance(typeFromHandle);
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
			List<MethodInfo> list = (from x in typeFromHandle.GetMethods(bindingAttr)
				where x.Name == "Ini"
				select x).ToList();
			if (list.Count > 0)
			{
				this.LoadIniHandler?.Invoke(this.Tinstance);
				list[0].Invoke(this.Tinstance, null);
			}
			MethodInfo[] methods = typeFromHandle.GetMethods(bindingAttr);
			MethodInfo[] array = methods;
			foreach (MethodInfo each in array)
			{
				TaskComAttribute taskCom = each.GetCustomAttribute<TaskComAttribute>();
				if (taskCom == null)
				{
					continue;
				}
				MyTask myTask = new MyTask(this.Tinstance);
				myTask.InitializeMethod = methods.FirstOrDefault((MethodInfo x) => x.Name == each.Name + "Ini");
				ManualResetEvent manualReset = new ManualResetEvent(taskCom.ImmediateExcute);
				CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
				if (taskCom.IsRecordCycleTime)
				{
					myTask.RecordCycleBuffer = new Queue<long>(1);
				}
				myTask.MethodName = each.Name;
				myTask.Function = taskCom.Function;
				myTask.ManualReset = manualReset;
				if (!taskCom.IsRunTime)
				{
					try
					{
						Task task = new Task(delegate
						{
							Stopwatch wt = base.BeginRecord(taskCom.IsRecordCycleTime);
							manualReset.WaitOne();
							Task.Delay(taskCom.DeleyTime, cancellationTokenSource.Token).Wait(cancellationTokenSource.Token);
							myTask.ExcuteInitialize();
							each.Invoke(this.Tinstance, null);
							base.EndRecord(wt, myTask, taskCom.RecordCycleTimePoint);
						}, cancellationTokenSource.Token);
						myTask.TaskNow = task;
						myTask.TokenSource = cancellationTokenSource;
						if (taskCom.SaveTask && !base.DicTask.ContainsKey(each.Name))
						{
							base.DicTask.Add(each.Name, myTask);
						}
						task.Start();
					}
					catch (Exception exception)
					{
						myTask.Exception = exception;
					}
					continue;
				}
				Task task2 = new Task(delegate
				{
					if (taskCom.IsRecordCycleTime)
					{
						myTask.RecordCycleBuffer = new Queue<long>(taskCom.RecordCycleTimePoint);
					}
					if (taskCom.DeleyTime > 0)
					{
						Thread.Sleep(taskCom.DeleyTime);
					}
					while (!cancellationTokenSource.IsCancellationRequested)
					{
						try
						{
							Stopwatch stopwatch = base.BeginRecord(taskCom.IsRecordCycleTime);
							stopwatch?.Reset();
							stopwatch?.Start();
							manualReset.WaitOne();
							myTask.ExcuteInitialize();
							each.Invoke(this.Tinstance, null);
							Thread.Sleep(taskCom.SleepTime);
							base.EndRecord(stopwatch, myTask, taskCom.RecordCycleTimePoint);
						}
						catch (Exception exception2)
						{
							myTask.Exception = exception2;
						}
					}
				}, cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
				if (taskCom.SaveTask && !base.DicTask.ContainsKey(each.Name))
				{
					myTask.TaskNow = task2;
					myTask.TokenSource = cancellationTokenSource;
					base.DicTask.Add(each.Name, myTask);
				}
				task2.Start();
			}
		}
	}
	public class TaskManager : BaseTask
	{
		private int _sleepTime;

		private bool _isRunTime;

		private bool _immediateExcute;

		private int _deleyTime;

		public bool SaveTask { get; set; }

		/// <summary>
		/// 启动任务
		/// </summary>
		/// <param name="action">实时方法</param>
		/// <param name="isRunTime">是否是实时运行</param>
		/// <param name="sleepTime">线程休眠时间</param>
		/// <param name="immediateExcute">立即执行</param>
		/// <param name="deleyTime">延时时间</param>
		/// <param name="callBack">回调</param>
		/// <exception cref="T:System.ArgumentNullException"></exception>
		/// <exception cref="T:System.Exception"></exception>
		public void Start(Action action, bool isRunTime, int sleepTime = 0, bool immediateExcute = true, int deleyTime = 0, Action<Task> callBack = null)
		{
			if (action == null)
			{
				throw new ArgumentNullException();
			}
			MethodInfo methodInfo = action.GetMethodInfo();
			string name = base.GetName(action);
			if (base.DicTask.ContainsKey(name))
			{
				throw new Exception("当前任务已经存在！");
			}
			this._sleepTime = sleepTime;
			this._deleyTime = deleyTime;
			MyTask myTask = new MyTask();
			ManualResetEvent manualReset = new ManualResetEvent(immediateExcute);
			CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
			myTask.MethodName = methodInfo.Name;
			myTask.ManualReset = manualReset;
			if (!isRunTime)
			{
				Task task = new Task(delegate
				{
					manualReset.WaitOne();
					Thread.Sleep(this._deleyTime);
					action();
				}, cancellationTokenSource.Token);
				if (this.SaveTask && !base.DicTask.ContainsKey(name))
				{
					myTask.TaskNow = task;
					myTask.TokenSource = cancellationTokenSource;
					base.DicTask.Add(name, myTask);
				}
				if (callBack != null)
				{
					task.ContinueWith(callBack, cancellationTokenSource.Token);
				}
				task.Start();
				return;
			}
			Task task2 = new Task(delegate
			{
				Task.Delay(this._deleyTime, cancellationTokenSource.Token).Wait(cancellationTokenSource.Token);
				while (!cancellationTokenSource.IsCancellationRequested)
				{
					manualReset.WaitOne();
					action();
					Thread.Sleep(this._sleepTime);
				}
			}, cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
			if (this.SaveTask && !base.DicTask.ContainsKey(name))
			{
				myTask.TaskNow = task2;
				myTask.TokenSource = cancellationTokenSource;
				base.DicTask.Add(name, myTask);
			}
			if (callBack != null)
			{
				task2.ContinueWith(callBack, cancellationTokenSource.Token);
			}
			task2.Start();
		}

		public void Start(Action action, int sleepTime = 0, int deleyTime = 0, Action<Task> callBack = null)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			this._isRunTime = sleepTime > 0;
			this._immediateExcute = deleyTime <= 0;
			this.Start(action, this._isRunTime, sleepTime, this._immediateExcute, deleyTime, callBack);
		}

		/// <summary>
		/// 延时执行方法
		/// </summary>
		/// <param name="action">方法</param>
		/// <param name="waitTime">等待时间</param>
		/// <param name="isAsync">是否是异步执行</param>
		/// <returns></returns>
		public static async void RunDelay(Action action, int waitTime, bool isAsync = false)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			await Task.Delay(waitTime);
			if (isAsync)
			{
				Task.Run(delegate
				{
					action();
				});
			}
			else
			{
				action();
			}
		}

		/// <summary>
		///  常用于超时任务启动
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="func">委托方法</param>
		/// <param name="timeout">超时设定</param>
		/// <returns>任务，委托方法异常与超时异常</returns>
		public static OperateResult<T> StartToDo<T>(Func<T> func, int timeout = 5000)
		{
			if (func == null)
			{
				throw new ArgumentNullException("func");
			}
			DateTime now = DateTime.Now;
			OperateResult<T> operateResult = new OperateResult<T>
			{
				Message = ""
			};
			Task<T> task = new Task<T>(func);
			task.Start();
			try
			{
				task.Wait(timeout);
			}
			catch (Exception ex)
			{
				operateResult.Message = ex.ToString();
				return operateResult;
			}
			DateTime now2 = DateTime.Now;
			double value = TimeHelper.TimeDecSum(now, now2);
			if (!task.IsCompleted)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 2);
				defaultInterpolatedStringHandler.AppendLiteral("任务超时TimetouSet=");
				defaultInterpolatedStringHandler.AppendFormatted(timeout);
				defaultInterpolatedStringHandler.AppendLiteral(",timeoutActual=");
				defaultInterpolatedStringHandler.AppendFormatted(value, "0.00");
				operateResult.Message = defaultInterpolatedStringHandler.ToStringAndClear();
				return operateResult;
			}
			operateResult.Content = task.Result;
			operateResult.IsSuccess = true;
			return operateResult;
		}

		/// <summary>
		///  常用于超时任务启动
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="func">委托方法</param>
		/// <param name="timeout">超时设定</param>
		/// <returns>任务，委托方法异常与超时异常</returns>
		public static OperateResult StartToDo(Action act, int timeout = 5000)
		{
			if (act == null)
			{
				throw new ArgumentNullException("act");
			}
			DateTime now = DateTime.Now;
			OperateResult operateResult = new OperateResult
			{
				Message = ""
			};
			Task task = new Task(act);
			task.Start();
			try
			{
				task.Wait(timeout);
			}
			catch (Exception ex)
			{
				operateResult.Message = ex.ToString();
				return operateResult;
			}
			DateTime now2 = DateTime.Now;
			double value = TimeHelper.TimeDecSum(now, now2);
			if (!task.IsCompleted)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 2);
				defaultInterpolatedStringHandler.AppendLiteral("任务超时TimetouSet=");
				defaultInterpolatedStringHandler.AppendFormatted(timeout);
				defaultInterpolatedStringHandler.AppendLiteral(",timeoutActual=");
				defaultInterpolatedStringHandler.AppendFormatted(value, "0.00");
				operateResult.Message = defaultInterpolatedStringHandler.ToStringAndClear();
				return operateResult;
			}
			operateResult.IsSuccess = true;
			return operateResult;
		}

		/// <summary>
		///  常用于超时任务启动
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="func">委托方法</param>
		/// <param name="timeout">超时设定</param>
		/// <returns>任务，委托方法异常与超时异常</returns>
		public static Tuple<Task<T>, Exception> StartTo<T>(Func<T> func, int timeout = 5000)
		{
			DateTime now = DateTime.Now;
			Task<T> task = new Task<T>(func);
			task.Start();
			try
			{
				task.Wait(timeout);
			}
			catch (Exception item)
			{
				return new Tuple<Task<T>, Exception>(task, item);
			}
			DateTime now2 = DateTime.Now;
			double value = TimeHelper.TimeDecSum(now, now2);
			if (!task.IsCompleted)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 2);
				defaultInterpolatedStringHandler.AppendLiteral("任务超时TimetouSet=");
				defaultInterpolatedStringHandler.AppendFormatted(timeout);
				defaultInterpolatedStringHandler.AppendLiteral(",timeoutActual=");
				defaultInterpolatedStringHandler.AppendFormatted(value, "0.00");
				return new Tuple<Task<T>, Exception>(task, new Exception(defaultInterpolatedStringHandler.ToStringAndClear()));
			}
			return new Tuple<Task<T>, Exception>(task, null);
		}

		/// <summary>
		/// 常用于超时任务启动
		/// </summary>
		/// <param name="act">委托方法</param>
		/// <param name="timeout">超时设定</param>
		/// <returns>任务，委托方法异常与超时异常</returns>
		public static Tuple<Task, Exception> StartTo(Action act, int timeout = 5000)
		{
			DateTime now = DateTime.Now;
			Task task = new Task(act);
			task.Start();
			try
			{
				task.Wait(timeout);
			}
			catch (Exception item)
			{
				return new Tuple<Task, Exception>(task, item);
			}
			DateTime now2 = DateTime.Now;
			double value = TimeHelper.TimeDecSum(now, now2);
			if (!task.IsCompleted)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 2);
				defaultInterpolatedStringHandler.AppendLiteral("任务超时TimetouSet=");
				defaultInterpolatedStringHandler.AppendFormatted(timeout);
				defaultInterpolatedStringHandler.AppendLiteral(",timeoutActual=");
				defaultInterpolatedStringHandler.AppendFormatted(value, "0.00");
				return new Tuple<Task, Exception>(task, new Exception(defaultInterpolatedStringHandler.ToStringAndClear()));
			}
			return new Tuple<Task, Exception>(task, null);
		}
	}
}
